home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / src / xad_DImp.lha / DImp.c < prev    next >
C/C++ Source or Header  |  2000-08-20  |  11KB  |  392 lines

  1. /* Disk Imploder (DImp) disk archiver client for XAD.
  2.  * Copyright (C) 2000 Stuart Caie <kyzer@4u.net>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  * 
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. /* This XAD client reads DImp disk files, either normal data files
  20.  * or ones with executable headers (1.00 and 2.27 headers known),
  21.  * and writes them out as ADF files, or  allows them to be written
  22.  * to standard Amiga formatted disks.
  23.  * The DImp format is (C) 1988-1991 Albert-Jan Brouwer
  24.  *
  25.  * $VER: DImp.c 1.2 (20.08.2000)
  26.  */
  27.  
  28. #include <exec/memory.h>
  29. #include <libraries/xadmaster.h>
  30. #include <proto/xadmaster.h>
  31.  
  32. #include "SDI_compiler.h"
  33. #include "ConvertE.c"
  34.  
  35. #ifndef XADMASTERFILE
  36. #define DImp_Client      FirstClient
  37. #define NEXTCLIENT      NULL
  38. const UBYTE version[] = "$VER: DImp 1.2 (20.08.2000)";
  39. #endif
  40. #define DIMP_VERSION     1
  41. #define DIMP_REVISION    2
  42.  
  43. #define XADBASE REG(a6, struct xadMasterBase *xadMasterBase)
  44.  
  45. /* work-doing macros */
  46. #define SKIP(offset) if ((err = xadHookAccess(XADAC_INPUTSEEK, \
  47.   (ULONG)(offset), NULL, ai))) goto exit_handler
  48. #define READ(buffer,length) if ((err = xadHookAccess(XADAC_READ, \
  49.   (ULONG)(length), (APTR)(buffer), ai))) goto exit_handler
  50. #define WRITE(buffer,length) if ((err = xadHookAccess(XADAC_WRITE, \
  51.   (ULONG)(length), (APTR)(buffer), ai))) goto exit_handler
  52. #define COPY(length) if ((err = xadHookAccess(XADAC_COPY, \
  53.   (ULONG)(length), NULL, ai))) goto exit_handler
  54. #define ALLOC(t,v,l) if (!((v) = (t) xadAllocVec((l),MEMF_CLEAR))) \
  55.   ERROR(NOMEMORY)
  56. #define ALLOCOBJ(t,v,kind,tags) \
  57.   if (!((v) = (t) xadAllocObjectA((kind),(tags)))) ERROR(NOMEMORY)
  58. #define FREE(obj) xadFreeObjectA((APTR)(obj),NULL)
  59. #define ERROR(error) do { err = XADERR_##error; goto exit_handler; } while(0)
  60.  
  61.  
  62.  
  63.  
  64. #define DIMP_CYLSIZE  (2*11*512)
  65.  
  66. /* DImp's info-table */
  67. #define dinf_cksum      (0)   /* ULONG checksum               */
  68. #define dinf_compmode   (4)   /* UWORD compression_mode       */
  69. #define dinf_bitmap     (6)   /* UBYTE disk_bitmap[10]        */
  70. #define dinf_ctable1    (16)  /* UBYTE compression_table1[28] */
  71. #define dinf_ctable2    (44)  /* UBYTE compression_table2[28] */
  72. #define dinf_textplen   (72)  /* ULONG textmsg_packed_len     */
  73. #define dinf_textulen   (76)  /* ULONG textmsg_unpacked_len   */
  74. #define dinf_textcksum  (80)  /* ULONG textmsg_checksum       */
  75. #define dinf_cylinfo    (84)  /* ULONG cylinder_info[80]      */
  76. #define dinf_SIZEOF     (404) /* ...maximum length            */
  77.  
  78. int DImp_bitmap(UBYTE *info, int track) {
  79.   return info[dinf_bitmap + (track>>3)] & (1 << (7-(track&7)));
  80. }
  81.  
  82. ULONG DImp_checksum(UBYTE *data, ULONG len) {
  83.   ULONG cksum = 0;
  84.   while (len > 1) {
  85.     cksum += EndGetM16(data);
  86.     data += 2; len -= 2;
  87.   }
  88.   if (len) cksum += (*data << 8);
  89.   return (cksum+7) & 0xFFFFFFFF;
  90. }
  91.  
  92.  
  93. /* de-implosion */
  94.  
  95. /* add.b d3,d3; bne gotbit; move.b -(a3),d3; addx.b d3,d3; gotbit: */
  96. #define GETBIT do { \
  97.  bit = bitbuf & 0x80; bitbuf <<= 1; \
  98.  if (!bitbuf) { bit2 = bit; bitbuf = *--inp; bit = bitbuf & 0x80; \
  99.    bitbuf <<= 1; if (bit2) bitbuf++; }; \
  100. } while (0)
  101.  
  102. static UBYTE explode_tab1[] = { 6, 10, 10, 18 };
  103. static UBYTE explode_tab2[] = { 1, 1, 1, 1, 2, 3, 3, 4, 4, 5, 7, 14 };
  104.  
  105. int DImp_explode(UBYTE *buf, UBYTE *table, ULONG inlen, ULONG outlen) {
  106.   UBYTE *inp  = buf + inlen-5;
  107.   UBYTE *outp = buf + outlen;
  108.   UBYTE *rep, bitbuf, bit, bit2;
  109.   ULONG litlen, matchlen, x, y, z;
  110.  
  111.   if (inlen & 1) {
  112.     bitbuf = inp[4];
  113.     litlen = EndGetM32(inp);
  114.   }
  115.   else {
  116.     bitbuf = inp[0];
  117.     litlen = EndGetM32(inp+1);
  118.   }
  119.  
  120.   while (1) {
  121.     if (outp-litlen < buf) return 0;
  122.     while (litlen--) *--outp = *--inp;
  123.  
  124.     /* main exit point - after the literal copy */
  125.     if (outp <= buf) break;
  126.  
  127.     GETBIT; if (bit) {
  128.       GETBIT; if (bit) {
  129.         GETBIT; if (bit) {
  130.           GETBIT; if (bit) {
  131.             matchlen = 0;
  132.             GETBIT; if (bit) {
  133.               x = 3;
  134.               matchlen = *--inp - 1;
  135.             }
  136.             else {
  137.               x = 3;
  138.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  139.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  140.               matchlen <<= 1; GETBIT; if (bit) matchlen++;
  141.               matchlen += 5;
  142.             }
  143.           } else x=3, matchlen=4;
  144.         } else x=2, matchlen=3;
  145.       } else x=1, matchlen=2;
  146.     } else x=0, matchlen=1;
  147.  
  148.     y = 0;
  149.     z = x;
  150.     GETBIT; if (bit) {
  151.       GETBIT; if (bit) {
  152.         y = explode_tab1[x];
  153.         x += 8;
  154.       }
  155.       else {
  156.         y = 2;
  157.         x += 4;
  158.       }
  159.     }
  160.  
  161.     x = explode_tab2[x];
  162.     litlen = 0;
  163.     while (x--) { litlen<<=1; GETBIT; if (bit) litlen++; }
  164.     litlen += y;
  165.  
  166.     rep = outp + 1;
  167.     x = z;
  168.  
  169.     GETBIT; if (bit) {
  170.       z <<= 1; GETBIT;
  171.       if (bit) { rep += EndGetM16(table+z+8); x += 8; }
  172.       else     { rep += EndGetM16(table+z);   x += 4; }
  173.     }
  174.     x = table[x+16];
  175.  
  176.     y = 0;
  177.     while (x--) { y<<=1; GETBIT; if (bit) y++; }
  178.     rep += y;
  179.  
  180.     if (outp-matchlen < buf) return 0;
  181.     do { *--outp = *--rep; } while (matchlen--);
  182.   }
  183.  
  184.   /* return 1 if we used up all input bytes (as we should) */
  185.   return (inp == buf);
  186. }
  187.  
  188.  
  189.  
  190.  
  191. ASM(BOOL) DImp_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *d), XADBASE) {
  192.   ULONG infolen;
  193.   if (d[0]!='D' || d[1]!='I' || d[2]!='M' || d[3]!='P') return 0;
  194.   infolen = EndGetM32(d+4);
  195.   return (BOOL) (infolen > 4 && infolen <= dinf_SIZEOF);
  196. }
  197.  
  198. ASM(LONG) SAVEDS DImp_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  199.   UBYTE buffer[8], *info, *text;
  200.   ULONG infolen, textplen, textulen;
  201.   struct xadDiskInfo *di = NULL;
  202.   struct xadTextInfo *ti;
  203.   LONG err = XADERR_OK;
  204.   int x;
  205.  
  206.   ALLOCOBJ(struct xadDiskInfo *, di, XADOBJ_DISKINFO, NULL);
  207.   ai->xai_DiskInfo     = di;
  208.   di->xdi_EntryNumber  = 1;
  209.   di->xdi_SectorSize   = 512;
  210.   di->xdi_TotalSectors = 80 * 22;
  211.   di->xdi_Cylinders    = 80;
  212.   di->xdi_CylSectors   = 22;
  213.   di->xdi_Heads        = 2;
  214.   di->xdi_TrackSectors = 11;
  215.  
  216.   /* read "DIMP" and info table length */
  217.   READ(buffer, 8);
  218.   infolen = EndGetM32(buffer+4);
  219.  
  220.   /* allocate and read info table */
  221.   ALLOC(UBYTE *, info, dinf_SIZEOF);
  222.   ai->xai_PrivateClient = (APTR) info;
  223.   READ(info, infolen);
  224.  
  225.   /* info table checksum */
  226.   if (EndGetM32(info+dinf_cksum) != DImp_checksum(info+4, infolen-4))
  227.     ERROR(CHECKSUM);
  228.  
  229.   /* look for start and end cylinders */
  230.   for (x=0; x<80; x++) if (DImp_bitmap(info, x)) break;
  231.   di->xdi_LowCyl = x;
  232.   if (x == 80) ERROR(EMPTY);
  233.  
  234.   for (x=79; x>=0; x--) if (DImp_bitmap(info, x)) break;
  235.   di->xdi_HighCyl = x;
  236.  
  237.  
  238.   textplen = EndGetM32(info+dinf_textplen);
  239.   textulen = EndGetM32(info+dinf_textulen);
  240.  
  241.   di->xdi_Flags   = XADDIF_SEEKDATAPOS;
  242.   di->xdi_DataPos = ai->xai_InPos + textplen;
  243.  
  244.   if (textulen) {
  245.     ALLOCOBJ(struct xadTextInfo *, ti, XADOBJ_TEXTINFO, NULL);
  246.     ALLOC(UBYTE *, text, (ti->xti_Size = textulen)+1);
  247.     di->xdi_TextInfo = ti;
  248.     ti->xti_Text     = text;
  249.  
  250.     READ(text, textplen);
  251.     text[textulen] = 0;
  252.  
  253.     if (textulen != textplen && !DImp_explode(text, info+dinf_ctable1,
  254.       textplen, textulen)) ERROR(DECRUNCH);
  255.   }
  256.  
  257. exit_handler:
  258.   if (err) {
  259.     if (!di) return err;
  260.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  261.     ai->xai_LastError = err;
  262.   }
  263.   return XADERR_OK;
  264. }
  265.  
  266.  
  267. ASM(LONG) SAVEDS DImp_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  268.   UBYTE *buf = NULL, *info = (UBYTE *) ai->xai_PrivateClient, *p;
  269.   struct xadDiskInfo *di = ai->xai_CurDisk;
  270.   ULONG cyl, x;
  271.   LONG err;
  272.  
  273.   ALLOC(UBYTE *, buf, DIMP_CYLSIZE);
  274.   for (cyl = di->xdi_LowCyl; cyl <= ai->xai_HighCyl; cyl++) {
  275.     if (cyl >= ai->xai_LowCyl) {
  276.       /* extracting */
  277.  
  278.       /* clear the buffer */
  279.       p=buf; x=DIMP_CYLSIZE; while (x--) *p++ = 0;
  280.  
  281.       if (DImp_bitmap(info, cyl)) {
  282.         x = EndGetM32(info+dinf_cylinfo+(cyl<<2));
  283.         if (x != 0xFFFFFFFF && x != 0) {
  284.           UWORD length = x >> 16;
  285.  
  286.           if (length > DIMP_CYLSIZE) ERROR(INPUT);
  287.           READ(buf, length);
  288.  
  289.           if ((DImp_checksum(buf, length) & 0xFFFF) != (x & 0xFFFF))
  290.             ERROR(CHECKSUM);
  291.  
  292.           if (length != DIMP_CYLSIZE && !DImp_explode(buf,
  293.             info+dinf_ctable2, length, DIMP_CYLSIZE)) ERROR(DECRUNCH);
  294.         }
  295.       }
  296.       WRITE(buf, DIMP_CYLSIZE);
  297.     }
  298.     else {
  299.       /* skipping */
  300.       if (DImp_bitmap(info, cyl)) {
  301.         x = EndGetM32(info+dinf_cylinfo+(cyl<<2));
  302.         if (x != 0xFFFFFFFF && x != 0) SKIP(x >> 16);
  303.       }
  304.     }
  305.   }
  306.  
  307. exit_handler:
  308.   if (buf) FREE(buf);
  309.   return err;
  310. }
  311.  
  312. ASM(void) DImp_Free(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  313.   if (ai->xai_PrivateClient) {
  314.     FREE(ai->xai_PrivateClient);
  315.     ai->xai_PrivateClient = NULL;
  316.   }
  317. }
  318.  
  319.  
  320.  
  321.  
  322. #define HUNK_HEADER    1011
  323. #define HUNK_CODE    1001
  324.  
  325. ASM(BOOL) DImpSFX_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *d), XADBASE) {
  326.   ULONG i;
  327.   if (size < 32
  328.   ||  EndGetM32(d)    != HUNK_HEADER
  329.   ||  EndGetM32(d+24) != HUNK_CODE) return 0;
  330.  
  331.   /* specific cases: DImp 1.00 = 3856; DImp 2.27 = 5796 */
  332.   if ((size >= 3860 && EndGetM32(d+3856) == 0x44494D50)
  333.   ||  (size >= 5800 && EndGetM32(d+5796) == 0x44494D50)) return 1;
  334.  
  335.   /* generic case - look just past the code hunk */
  336.   for (i = (EndGetM32(d+28)<<2) + 36; i < size; i+=4) {
  337.     if (EndGetM32(d+i) == 0x44494D50) return 1;
  338.   }
  339.  
  340.   return 0;
  341. }
  342.  
  343. ASM(LONG) DImpSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  344.   ULONG readlen, offset = 0, i;
  345.   UBYTE *buf;
  346.   LONG err;
  347.  
  348.   readlen = ai->xai_InSize;
  349.   if (readlen > 6144) readlen = 6144;
  350.  
  351.   ALLOC(UBYTE *, buf, readlen);
  352.   READ(buf, readlen);
  353.  
  354.   for (i = (EndGetM32(buf+28)<<2) + 36; i < readlen; i+=4) {
  355.     if (EndGetM32(buf+i) == 0x44494D50) { offset = i; break; }
  356.   }
  357.  
  358.   err = XADERR_DATAFORMAT;
  359.  
  360. exit_handler:
  361.   if (buf) FREE(buf);
  362.  
  363.   /* if we found a match, actually look at the archive */
  364.   if (offset != 0) {
  365.     SKIP(offset - ai->xai_InPos);
  366.     err = DImp_GetInfo(ai, xadMasterBase);
  367.   }
  368.   return err;
  369. }
  370.  
  371.  
  372. const struct xadClient DImpSFX_Client = {
  373.   NEXTCLIENT, XADCLIENT_VERSION, 4, DIMP_VERSION, DIMP_REVISION,
  374.   6144, XADCF_DISKARCHIVER|XADCF_FREEDISKINFO|XADCF_NOCHECKSIZE,
  375.   0, "DImp SFX",
  376.   (BOOL (*)()) DImpSFX_RecogData,
  377.   (LONG (*)()) DImpSFX_GetInfo,
  378.   (LONG (*)()) DImp_UnArchive,
  379.   (void (*)()) DImp_Free
  380. };
  381.  
  382. const struct xadClient DImp_Client = {
  383.   (struct xadClient *) &DImpSFX_Client, XADCLIENT_VERSION, 4,
  384.   DIMP_VERSION, DIMP_REVISION,
  385.   10, XADCF_DISKARCHIVER|XADCF_FREEDISKINFO,
  386.   0, "DImp",
  387.   (BOOL (*)()) DImp_RecogData,
  388.   (LONG (*)()) DImp_GetInfo,
  389.   (LONG (*)()) DImp_UnArchive,
  390.   (void (*)()) DImp_Free
  391. };
  392.